Popular Searches
Popular Course Categories
Popular Courses

Implementing Email and Password Authentication

Implementing Email and Password Authentication

Authentication and User Account Management

Implementing Email and Password Authentication in React Native

Course: React Native Training

Topic: Implementing Email and Password Authentication

Course Link: React Native Training at JustAcademy

Demo Link: Register for a Course Demo

Website: JustAcademy Official Website


1. Introduction to Email and Password Authentication

Email and password authentication is a common method used to verify the identity of users in mobile applications. Users create an account with an email address and password, then use those credentials to sign in to the application.

In React Native, authentication can be implemented using an authentication service such as Firebase Authentication or a custom backend built with technologies such as Node.js, Express, and a database.

A complete authentication system generally includes account registration, sign-in, input validation, password recovery, email verification, session management, sign-out, and protected screens.

1.1 What Is Authentication?

Authentication is the process of verifying that a user is who they claim to be. When a user enters an email address and password, the authentication system checks the credentials and establishes an authenticated session if they are valid.

Authentication is different from authorization. Authentication verifies identity, while authorization determines which resources or operations that identity is allowed to access.

1.2 Why Is Authentication Important?

  • It allows users to create personal accounts.
  • It protects user-specific information.
  • It supports personalized application experiences.
  • It allows applications to maintain user sessions.
  • It provides a foundation for role-based access control.
  • It supports account recovery and identity verification.
  • It helps applications associate saved information with a specific user.

1.3 Examples of Applications Using Authentication

  • E-learning applications with personal course progress.
  • E-commerce applications with order histories.
  • Banking applications with protected account information.
  • Fitness applications with personal activity records.
  • Social applications with user profiles and private content.
  • Business applications with role-specific dashboards.

2. Learning Objectives

After completing this topic, learners should be able to:

  • Explain email and password authentication.
  • Understand authentication and authorization.
  • Create registration and login screens in React Native.
  • Connect a React Native application to an authentication provider.
  • Implement form validation and password visibility controls.
  • Handle registration and login errors.
  • Maintain authentication state across application sessions.
  • Implement sign-out and password recovery.
  • Understand email verification and protected screens.
  • Apply security and privacy best practices.
  • Test authentication flows on Android and iOS.

3. How Email and Password Authentication Works

The authentication process involves the mobile application, an authentication service or backend, and a secure method for maintaining the user's authenticated state.

3.1 Registration Workflow

  1. The user opens the registration screen.
  2. The user enters an email address and password.
  3. The application validates the input.
  4. The application sends the credentials securely to the authentication service.
  5. The service validates the request and creates the account.
  6. The service returns an authentication result or an error.
  7. The application updates the authentication state.
  8. The user is directed to the appropriate next screen, such as email verification or the home screen.

3.2 Login Workflow

  1. The user enters the registered email address and password.
  2. The application validates the form.
  3. The credentials are sent to the authentication service over a secure connection.
  4. The service checks the credentials.
  5. If valid, the service establishes or refreshes an authenticated session.
  6. The application updates its authentication state.
  7. The user can access the screens permitted by the account's authorization.

3.3 Authentication Flow Diagram

          React Native App
                 |
                 v
       Registration / Login Form
                 |
                 v
        Validate User Input
                 |
                 v
      Authentication Service
                 |
          +------+------+
          |             |
          v             v
      Success          Failure
          |             |
          v             v
   Update Auth State   Show Error
          |
          v
   Protected App Screens

4. Choosing an Authentication Solution

Before implementing authentication, choose an approach that fits the application's requirements.

Approach Description Suitable For
Firebase Authentication Managed authentication service with client SDKs and account-management features Applications that need a ready-made authentication provider
React Native Firebase React Native integration with native Firebase SDKs Projects that want native Firebase integration
Firebase JavaScript SDK JavaScript SDK that can be used in compatible React Native projects Projects using the JavaScript SDK, with appropriate React Native persistence configuration
Custom backend A server verifies credentials and manages sessions or tokens Applications requiring custom authentication rules and backend control
Identity provider A dedicated identity platform manages authentication and account features Applications requiring enterprise or advanced identity features

These approaches are alternatives rather than dependencies that must all be installed together. The examples below use Firebase Authentication with the Firebase JavaScript SDK for a React Native project. React Native Firebase is discussed separately.

5. Setting Up Firebase Authentication

Firebase Authentication provides services for creating accounts, signing in, handling password recovery, verifying email addresses, and observing authentication state.

5.1 Create a Firebase Project

  1. Open the Firebase Console.
  2. Create a new project or open an existing project.
  3. Add and configure the application according to the selected React Native setup.
  4. Open the Authentication section.
  5. Navigate to the sign-in provider settings.
  6. Enable the Email/Password provider and save the changes.

5.2 Install the Required Packages

For a project using the Firebase JavaScript SDK, install Firebase and AsyncStorage:

npm install firebase
npx expo install @react-native-async-storage/async-storage

The AsyncStorage package is used in the example to configure React Native persistence for the Firebase JavaScript SDK. If the project uses another supported persistence solution, configure it according to the relevant documentation.

5.3 Configure Firebase

Create a file named src/config/firebase.ts and initialize Firebase using the configuration values from your Firebase project.

// src/config/firebase.ts
import { initializeApp } from 'firebase/app';
import {
  getAuth,
  initializeAuth,
  getReactNativePersistence
} from 'firebase/auth';
import AsyncStorage from '@react-native-async-storage/async-storage';

const firebaseConfig = {
  apiKey: 'YOUR_FIREBASE_API_KEY',
  authDomain: 'YOUR_PROJECT.firebaseapp.com',
  projectId: 'YOUR_PROJECT_ID',
  storageBucket: 'YOUR_STORAGE_BUCKET',
  messagingSenderId: 'YOUR_MESSAGING_SENDER_ID',
  appId: 'YOUR_APP_ID'
};

const app = initializeApp(firebaseConfig);

export const auth = initializeAuth(app, {
  persistence: getReactNativePersistence(AsyncStorage)
});

Important: Replace the placeholder values with the configuration for your Firebase project. This example initializes authentication with React Native persistence. Ensure Firebase is initialized only once; if the application already has an initialized Auth instance, reuse it rather than calling initializeAuth() repeatedly. The Firebase JavaScript SDK's React Native APIs can vary by SDK version, so consult the current official documentation if an import or initialization option differs in your installed version.

5.4 Firebase Setup Checklist

  • Firebase project created.
  • Application configuration added.
  • Email/Password authentication enabled.
  • Firebase package installed.
  • React Native persistence configured where required.
  • Configuration values checked.
  • Development and release environments reviewed.

6. Understanding the Authentication API

Firebase Authentication provides methods for account creation, login, logout, password reset, email verification, and authentication-state observation.

Method Purpose
createUserWithEmailAndPassword() Creates an account using an email address and password.
signInWithEmailAndPassword() Signs in an existing user.
signOut() Signs out the current user.
onAuthStateChanged() Observes authentication-state changes.
sendPasswordResetEmail() Sends a password-reset email.
sendEmailVerification() Sends an email-verification message.
updateProfile() Updates supported user profile fields.

These methods are provided by Firebase Authentication. Their exact behavior and supported options should be checked against the SDK version used by the project.

7. Creating a Registration Screen

The registration screen collects the email address and password, validates the fields, and calls the authentication service to create an account.

7.1 Registration Form Requirements

  • Email input.
  • Password input.
  • Confirm password input.
  • Register button.
  • Loading indicator while the request is running.
  • Validation and authentication error messages.
  • Navigation to the login screen for existing users.
  • Clear password and privacy guidance.

7.2 Example Registration Screen

import React, { useState } from 'react';
import {
  Alert,
  Button,
  Text,
  TextInput,
  View
} from 'react-native';
import { createUserWithEmailAndPassword } from 'firebase/auth';
import { auth } from '../config/firebase';

export default function RegisterScreen() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [confirmPassword, setConfirmPassword] = useState('');
  const [loading, setLoading] = useState(false);

  async function handleRegister() {
    const normalizedEmail = email.trim();

    if (!normalizedEmail || !password || !confirmPassword) {
      Alert.alert('Validation Error', 'Please complete all fields.');
      return;
    }

    if (password !== confirmPassword) {
      Alert.alert('Validation Error', 'Passwords do not match.');
      return;
    }

    if (password.length < 8) {
      Alert.alert(
        'Validation Error',
        'Use a password with at least 8 characters.'
      );
      return;
    }

    try {
      setLoading(true);

      await createUserWithEmailAndPassword(
        auth,
        normalizedEmail,
        password
      );

      Alert.alert('Success', 'Your account has been created.');
    } catch (error) {
      Alert.alert(
        'Registration Failed',
        'Unable to create the account. Check your details and try again.'
      );
    } finally {
      setLoading(false);
    }
  }

  return (
    <View>
      <Text>Create Account</Text>

      <TextInput
        placeholder="Email address"
        value={email}
        onChangeText={setEmail}
        keyboardType="email-address"
        autoCapitalize="none"
        autoComplete="email"
      />

      <TextInput
        placeholder="Password"
        value={password}
        onChangeText={setPassword}
        secureTextEntry
        autoCapitalize="none"
        autoComplete="new-password"
      />

      <TextInput
        placeholder="Confirm password"
        value={confirmPassword}
        onChangeText={setConfirmPassword}
        secureTextEntry
        autoCapitalize="none"
        autoComplete="new-password"
      />

      <Button
        title={loading ? 'Creating Account...' : 'Register'}
        onPress={handleRegister}
        disabled={loading}
      />
    </View>
  );
}

This example illustrates the registration flow. For production use, improve the form layout, use inline validation messages, disable repeated submissions, follow the Firebase project's configured password policy, and navigate based on the actual authentication state.

7.3 How Registration Works

  1. The user enters an email address and password.
  2. The application checks that the required fields are present.
  3. The application compares the password and confirmation fields.
  4. The authentication request is sent to Firebase.
  5. Firebase creates the account if the credentials satisfy its requirements.
  6. The application handles the success or error result.

8. Creating a Login Screen

The login screen allows existing users to access their accounts by entering the registered email address and password.

8.1 Login Form Requirements

  • Email input field.
  • Password input field.
  • Login button.
  • Loading indicator.
  • Invalid-credential feedback.
  • Forgot-password link.
  • Navigation to registration for new users.

8.2 Example Login Screen

import React, { useState } from 'react';
import {
  Alert,
  Button,
  Text,
  TextInput,
  View
} from 'react-native';
import { signInWithEmailAndPassword } from 'firebase/auth';
import { auth } from '../config/firebase';

export default function LoginScreen() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [loading, setLoading] = useState(false);

  async function handleLogin() {
    const normalizedEmail = email.trim();

    if (!normalizedEmail || !password) {
      Alert.alert(
        'Validation Error',
        'Enter your email address and password.'
      );
      return;
    }

    try {
      setLoading(true);

      await signInWithEmailAndPassword(
        auth,
        normalizedEmail,
        password
      );

      // Authentication state observer handles navigation.
    } catch (error) {
      Alert.alert(
        'Login Failed',
        'Unable to sign in with those details. Please try again.'
      );
    } finally {
      setLoading(false);
    }
  }

  return (
    <View>
      <Text>Welcome Back</Text>

      <TextInput
        placeholder="Email address"
        value={email}
        onChangeText={setEmail}
        keyboardType="email-address"
        autoCapitalize="none"
        autoComplete="email"
      />

      <TextInput
        placeholder="Password"
        value={password}
        onChangeText={setPassword}
        secureTextEntry
        autoCapitalize="none"
        autoComplete="current-password"
      />

      <Button
        title={loading ? 'Signing In...' : 'Login'}
        onPress={handleLogin}
        disabled={loading}
      />
    </View>
  );
}

8.3 Login Workflow Explanation

  • The email is trimmed to remove accidental leading and trailing spaces.
  • The password is not trimmed automatically because spaces may be part of a valid password.
  • The form prevents submission when required values are missing.
  • Firebase checks the credentials.
  • Authentication errors are handled without displaying sensitive diagnostic details.
  • The authentication-state listener determines whether the application should show the authenticated screens.

9. Input Validation

Input validation improves usability and prevents unnecessary authentication requests. However, client-side validation is not a replacement for validation performed by the authentication provider or backend.

9.1 Email Validation

Email validation should check that the field is not empty and that its format appears valid. A client-side check cannot prove that an address exists or belongs to the user. Email verification is needed when ownership must be confirmed.

function isValidEmail(email) {
  const normalizedEmail = email.trim();
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(normalizedEmail);
}

This expression is a simple client-side check, not a complete implementation of every valid email-address format.

9.2 Password Validation

Password rules should be based on the authentication provider's configured password policy and the application's security requirements.

  • Require a non-empty password.
  • Apply the configured minimum and maximum length.
  • Use appropriate password-strength guidance.
  • Avoid silently modifying the user's password.
  • Allow password managers to generate and fill secure passwords.
  • Provide clear guidance when a password does not meet the configured policy.

9.3 Confirm Password Validation

Confirm password is a user-interface check that helps detect typing mistakes during registration. The confirmation field does not normally need to be sent to the authentication provider.

if (password !== confirmPassword) {
  setError('Passwords do not match.');
  return;
}

9.4 Validation Best Practices

  • Show messages near the relevant fields.
  • Validate before making network requests.
  • Disable the submit button while a request is in progress.
  • Preserve the email field when an error occurs.
  • Avoid clearing a user's password unnecessarily after a temporary network failure.
  • Keep server-side or provider-side validation authoritative.

10. Password Visibility Controls

Password fields generally hide their contents by default. A visibility control allows users to reveal or conceal the password while entering it.

10.1 Example Implementation

import React, { useState } from 'react';
import { TextInput, View, Button } from 'react-native';

export default function PasswordField() {
  const [password, setPassword] = useState('');
  const [visible, setVisible] = useState(false);

  return (
    <View>
      <TextInput
        value={password}
        onChangeText={setPassword}
        placeholder="Password"
        secureTextEntry={!visible}
        autoCapitalize="none"
        autoComplete="current-password"
      />

      <Button
        title={visible ? 'Hide Password' : 'Show Password'}
        onPress={() => setVisible(previous => !previous)}
      />
    </View>
  );
}

10.2 Benefits

  • Reduces mistakes when typing complex passwords.
  • Improves usability on mobile devices.
  • Helps users check their input before submission.

The password should remain concealed by default, and the visibility control should be accessible and clearly labelled.

11. Managing Authentication State

Authentication state indicates whether a user is signed in. It should be managed centrally so that screens do not make conflicting decisions about whether a user is authenticated.

11.1 Why Authentication State Matters

  • It determines which screens should be displayed.
  • It supports persistent sessions when the provider offers persistence.
  • It updates the interface after login or logout.
  • It prevents unnecessary manual checks in individual screens.
  • It provides a consistent place to react to session expiration or changes.

11.2 Observe Firebase Authentication State

import { onAuthStateChanged } from 'firebase/auth';
import { auth } from './config/firebase';

const unsubscribe = onAuthStateChanged(auth, user => {
  if (user) {
    console.log('Authenticated user:', user.uid);
  } else {
    console.log('No authenticated user.');
  }
});

// Call unsubscribe() when the observer is no longer needed.

The observer is notified when the authentication state changes. In a React component, register it inside useEffect() and return the unsubscribe function during cleanup.

11.3 Example Authentication Context

import React, {
  createContext,
  useContext,
  useEffect,
  useState
} from 'react';
import { onAuthStateChanged } from 'firebase/auth';
import { auth } from '../config/firebase';

const AuthContext = createContext({
  user: null,
  initializing: true
});

export function AuthProvider({ children }) {
  const [user, setUser] = useState(null);
  const [initializing, setInitializing] = useState(true);

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, currentUser => {
      setUser(currentUser);
      setInitializing(false);
    });

    return unsubscribe;
  }, []);

  return (
    <AuthContext.Provider value={{ user, initializing }}>
      {children}
    </AuthContext.Provider>
  );
}

export function useAuth() {
  return useContext(AuthContext);
}

This context example provides the current user and an initialization flag. The application should wrap the relevant navigation tree with AuthProvider and use the context to select the appropriate screens.

12. Implementing Protected Screens

Protected screens should be available only to authenticated users. The application can use authentication state to choose between public screens and authenticated screens.

12.1 Example Conditional Rendering

import React from 'react';
import { ActivityIndicator, Text, View } from 'react-native';
import { useAuth } from './context/AuthContext';
import LoginScreen from './screens/LoginScreen';
import HomeScreen from './screens/HomeScreen';

export default function AppContent() {
  const { user, initializing } = useAuth();

  if (initializing) {
    return <ActivityIndicator size="large" />;
  }

  if (!user) {
    return <LoginScreen />;
  }

  return <HomeScreen />;
}

This example demonstrates conditional rendering. In a larger application, use a navigation library and separate authentication and application navigation stacks as appropriate.

12.2 Important Security Rule

Hiding a screen in React Native is not sufficient to protect private data. The backend or database must independently verify the user's identity and permissions before returning protected information or allowing changes.

13. Implementing Sign-Out

Sign-out ends the current authenticated session through the authentication provider. The application should then update its navigation state and return the user to the public screens.

13.1 Firebase Sign-Out Example

import { signOut } from 'firebase/auth';
import { Alert } from 'react-native';
import { auth } from '../config/firebase';

async function handleSignOut() {
  try {
    await signOut(auth);
  } catch (error) {
    Alert.alert(
      'Sign-Out Failed',
      'Unable to sign out. Please try again.'
    );
  }
}

When the authentication observer detects that the user is signed out, the application can display the login screen automatically.

13.2 Sign-Out Best Practices

  • Provide a clearly labelled sign-out action.
  • Update the application UI after sign-out.
  • Remove application-specific sensitive state from memory where appropriate.
  • Clear any separately managed session data according to the application's design.
  • Do not assume signing out of Firebase automatically signs out of unrelated services.

14. Password Reset and Account Recovery

Users may forget their passwords. A password recovery workflow allows them to request a reset email and choose a new password through a secure provider-managed flow.

14.1 Password Reset Workflow

  1. The user opens the Forgot Password screen.
  2. The user enters their email address.
  3. The application performs basic input validation.
  4. The application requests a password-reset email from the provider.
  5. The user opens the email and follows the secure reset link.
  6. The provider validates the reset request and allows the password to be changed.
  7. The user returns to the application and signs in using the updated credentials if required.

14.2 Example Password Reset Function

import { sendPasswordResetEmail } from 'firebase/auth';
import { auth } from '../config/firebase';

async function requestPasswordReset(email) {
  const normalizedEmail = email.trim();

  if (!normalizedEmail) {
    throw new Error('Enter your email address.');
  }

  await sendPasswordResetEmail(auth, normalizedEmail);
}

14.3 User-Friendly Feedback

Use neutral confirmation wording, such as: "If an account is associated with this address, password reset instructions will be sent." This helps avoid revealing whether a particular email address has an account.

15. Email Verification

Email verification allows the authentication provider to confirm that the user can access the email address associated with the account.

15.1 Why Verify Email Addresses?

  • It helps confirm control of the registered email address.
  • It supports account recovery workflows.
  • It can reduce mistakes caused by incorrectly entered email addresses.
  • It can support application policies that require verified email addresses.

15.2 Send an Email Verification Message

import { sendEmailVerification } from 'firebase/auth';
import { auth } from '../config/firebase';

async function sendVerificationEmail() {
  const user = auth.currentUser;

  if (!user) {
    throw new Error('No authenticated user.');
  }

  await sendEmailVerification(user);
}

15.3 Checking Verification Status

After the user follows the verification link, refresh the user's authentication data before checking the latest verification state when required.

import { reload } from 'firebase/auth';
import { auth } from '../config/firebase';

async function refreshVerificationStatus() {
  const user = auth.currentUser;

  if (!user) {
    return false;
  }

  await reload(user);
  return auth.currentUser?.emailVerified ?? false;
}

Verification status should be checked against the current user object after refreshing it. If access to sensitive features depends on verification, enforce that requirement on the backend or in database security rules as well.

16. Handling Authentication Errors

Authentication requests may fail because of invalid credentials, network problems, provider configuration, account restrictions, or password policy requirements.

Error Scenario Possible Cause Recommended Handling
Invalid email Email format is invalid Ask the user to check the email address.
Weak password Password does not meet the configured policy Explain the password requirements.
Email already in use An account already exists for the address Offer sign-in or account recovery without exposing unnecessary account information.
Invalid credentials Email or password is incorrect Display a neutral sign-in error and allow retry.
Provider disabled Email/password authentication is not enabled Enable the provider in the authentication configuration.
Network failure The device is offline or the service is unavailable Offer retry and show a connection-related message where appropriate.
Too many requests Rate limits or abuse protections have been triggered Ask the user to wait and retry later.
Session expired or invalid Authentication credentials or session are no longer valid Refresh the session if supported or ask the user to sign in again.

16.1 Avoid Exposing Internal Errors

Developer logs can contain useful error codes during debugging, but user-facing messages should be understandable and should not expose implementation details, sensitive data, or unnecessary information about registered accounts.

try {
  await signInWithEmailAndPassword(auth, email, password);
} catch (error) {
  console.error('Authentication failed:', error.code);

  setError(
    'Unable to sign in with those details. Please try again.'
  );
}

In production, ensure diagnostic logging does not include passwords, authentication tokens, or other sensitive information.

17. Password Security Best Practices

Password security is a critical part of authentication. The application should rely on a trusted authentication provider or a correctly designed backend instead of implementing password storage and verification carelessly.

  • Use a secure authentication provider or a well-reviewed backend implementation.
  • Never store plain-text passwords in a database, AsyncStorage, logs, or source code.
  • Use HTTPS for network communication with a custom authentication backend.
  • Enforce password policies on the authentication service, not only in the user interface.
  • Support password managers and appropriate autofill behavior.
  • Avoid logging credentials or authentication tokens.
  • Use generic login errors when detailed messages could expose account information.
  • Apply rate limiting and abuse prevention through the provider or backend.
  • Use multi-factor authentication where appropriate for the application's risk level.
  • Provide secure account recovery and email verification.

18. Managing Session Persistence

Session persistence allows users to remain signed in when they close and reopen the application, depending on the authentication provider's behavior and the configured persistence mechanism.

18.1 Why Persistence Matters

  • Users do not need to sign in every time they open the application.
  • The application can restore the correct screen after restarting.
  • Authentication state can be managed centrally.
  • The user experience becomes more consistent.

18.2 Persistence with Firebase JavaScript SDK

In React Native, configure an appropriate persistence mechanism for the Firebase JavaScript SDK. The earlier Firebase setup example uses initializeAuth() with getReactNativePersistence(AsyncStorage).

For a native Firebase integration, React Native Firebase manages authentication through its native SDK integration. Follow the setup instructions for the exact library selected by the project.

18.3 Security Considerations

  • Do not store raw passwords for session persistence.
  • Do not assume ordinary AsyncStorage is encrypted secure storage.
  • Use platform-appropriate secure storage for application secrets when needed.
  • Rely on the authentication provider's supported session and token management.
  • Handle sign-out and token expiration correctly.

19. Using React Native Firebase Instead

React Native Firebase is an alternative integration that uses native Firebase SDKs. It is suitable for projects that want Firebase functionality through native Android and iOS integrations.

19.1 Install the Packages

# Install the Firebase app module
npm install @react-native-firebase/app

# Install the authentication module
npm install @react-native-firebase/auth

Follow the official React Native Firebase setup guide to configure the Android and iOS applications, including the required Firebase configuration files. iOS projects may also require CocoaPods installation.

19.2 Example Login Function

import auth from '@react-native-firebase/auth';

async function loginWithEmail(email, password) {
  try {
    const result = await auth().signInWithEmailAndPassword(
      email.trim(),
      password
    );

    return result.user;
  } catch (error) {
    console.error('Sign-in failed:', error.code);
    throw error;
  }
}

This example uses the namespaced API style supported by relevant React Native Firebase versions. Check the documentation for the version installed in the project because API styles and recommended imports can differ.

19.3 JavaScript SDK vs React Native Firebase

Firebase JavaScript SDK React Native Firebase
Uses Firebase's JavaScript SDK Uses native Firebase SDK integration
Requires appropriate React Native persistence configuration when needed Uses native SDK session behavior
May fit Expo projects that use compatible JavaScript SDK features Requires native configuration and a compatible native build workflow
Some platform-specific capabilities may have different support Provides access through the native Firebase SDK integration

Choose one integration approach for the same Firebase Authentication workflow unless there is a clear, deliberate reason to combine SDKs. Avoid initializing competing authentication instances unintentionally.

20. Authentication with a Custom Backend

Some applications use a custom backend instead of Firebase Authentication. In this approach, the React Native app sends credentials to a server, which verifies them and returns a session or token according to its authentication design.

20.1 Typical Architecture

React Native App
       |
       | HTTPS request
       v
Backend API
       |
       v
Credential Verification
       |
       v
User Database
       |
       v
Session or Token Response
       |
       v
Authenticated Application

20.2 Example Login Request

async function loginWithBackend(email, password) {
  const response = await fetch(
    'https://api.example.com/auth/login',
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        email: email.trim(),
        password
      })
    }
  );

  if (!response.ok) {
    throw new Error('Unable to sign in.');
  }

  return response.json();
}

The URL is an example placeholder and must be replaced with the application's real HTTPS endpoint. This example does not define token storage or session management; those must be designed securely.

20.3 Backend Security Requirements

  • Use HTTPS for all credential and token exchanges.
  • Hash passwords using an established password-hashing algorithm with an appropriate work factor and unique salts.
  • Never store plain-text passwords.
  • Validate requests on the server.
  • Apply rate limits and abuse prevention.
  • Use secure session or token handling.
  • Check authorization on every protected API operation.
  • Provide secure password reset and account recovery.

21. Designing a Good Authentication User Interface

An authentication screen should be simple, accessible, and consistent. Clear labels and helpful error messages make the registration and login process easier to use.

21.1 UI Design Recommendations

  • Use clear labels and placeholders.
  • Provide appropriate keyboard types for email fields.
  • Disable automatic capitalization for email addresses.
  • Use secure text entry for passwords by default.
  • Provide a show/hide password option.
  • Display loading states during network requests.
  • Prevent accidental repeated submissions.
  • Keep buttons accessible to screen readers.
  • Show validation messages close to the relevant fields.
  • Provide links to registration, login, and password recovery screens.
  • Ensure the form works on smaller devices and with the keyboard open.

21.2 Accessibility Considerations

  • Give each input an accessible label.
  • Do not communicate errors using color alone.
  • Use sufficient text contrast.
  • Ensure touch targets are large enough.
  • Make loading and error states understandable to assistive technology.

22. Testing Email and Password Authentication

Authentication must be tested under both successful and unsuccessful conditions. Testing should cover registration, login, session restoration, recovery, verification, and sign-out.

22.1 Registration Test Cases

  • Register with a valid email address and compliant password.
  • Submit an empty form.
  • Enter an invalid email format.
  • Enter a password that does not meet the configured policy.
  • Enter mismatched confirmation passwords.
  • Attempt to register an existing email address.
  • Test a network failure during registration.

22.2 Login Test Cases

  • Sign in with valid credentials.
  • Enter an incorrect password.
  • Enter an unregistered email address.
  • Submit empty fields.
  • Test with an invalid email format.
  • Test offline behavior and service failures.
  • Confirm that repeated taps do not create unwanted duplicate requests.

22.3 Session and Account Test Cases

  • Close and reopen the application after successful login.
  • Verify that the correct screen appears during session restoration.
  • Sign out and confirm that protected screens are no longer displayed.
  • Request a password reset and follow the reset process.
  • Verify email ownership when required.
  • Test revoked, expired, or invalid sessions where supported.
  • Confirm that protected backend resources reject unauthenticated requests.

23. Common Problems and Troubleshooting

Problem Possible Cause Solution
Authentication provider disabled Email/Password is not enabled in Firebase Enable the provider in Firebase Authentication settings.
Firebase initialization error Incorrect configuration or duplicate initialization Verify configuration and initialize the Firebase app and Auth instance correctly.
User cannot register Invalid email, password policy failure, or existing account Check validation and handle provider error codes.
User cannot sign in Incorrect credentials or account state Show neutral feedback and provide password recovery.
User is logged out after restart Persistence is not configured as expected Review the selected SDK's persistence setup.
Password reset email not received Incorrect address, delivery delay, or provider configuration Check the address, spam folder, and email action settings.
Verification status seems outdated User profile has not been refreshed Reload the user and check the current verification status.
Protected API returns private data incorrectly Backend authorization is missing or incorrect Verify identity and authorization on the server or database rules.
App fails to compile after native SDK setup Native dependencies or configuration are incomplete Follow the provider's platform setup and rebuild instructions.

24. Practical Project: Email Authentication App

Project Objective: Build a React Native application with registration, login, authentication state management, password recovery, email verification, and sign-out.

24.1 Project Features

  • Registration screen with email, password, and confirm password.
  • Login screen for existing users.
  • Input validation and useful error messages.
  • Password visibility toggle.
  • Forgot password screen.
  • Email verification flow.
  • Central authentication context.
  • Protected home screen.
  • Sign-out functionality.
  • Session persistence according to the selected authentication SDK.

24.2 Suggested Project Structure

src/
├── config/
│   └── firebase.ts
├── context/
│   └── AuthContext.tsx
├── components/
│   ├── AuthInput.tsx
│   ├── PrimaryButton.tsx
│   └── ErrorMessage.tsx
├── screens/
│   ├── LoginScreen.tsx
│   ├── RegisterScreen.tsx
│   ├── ForgotPasswordScreen.tsx
│   ├── VerifyEmailScreen.tsx
│   └── HomeScreen.tsx
├── services/
│   └── authService.ts
└── App.tsx

24.3 Development Steps

  1. Create a React Native or Expo project.
  2. Configure Firebase Authentication or another suitable provider.
  3. Enable email/password authentication in the provider settings.
  4. Build reusable form inputs and buttons.
  5. Implement registration and login methods.
  6. Implement validation and error handling.
  7. Set up authentication-state observation.
  8. Configure the appropriate navigation flow.
  9. Implement password recovery and email verification.
  10. Implement sign-out and protected screens.
  11. Test successful and unsuccessful authentication scenarios.
  12. Review security and privacy before deployment.

24.4 Expected Learning Outcomes

After completing the project, learners should understand how to connect a React Native application to an authentication service, manage authenticated state, handle common authentication errors, and protect user-specific application experiences.

25. Practice Exercises

  1. Create a registration screen with email, password, and confirmation fields.
  2. Implement client-side email validation.
  3. Add a show/hide password control.
  4. Connect the login screen to Firebase Authentication.
  5. Display appropriate error messages for invalid credentials.
  6. Create an authentication context that observes login state.
  7. Build a protected home screen.
  8. Implement sign-out and confirm the navigation state updates correctly.
  9. Implement a password-reset request screen.
  10. Add an email-verification workflow.
  11. Test persistence after closing and reopening the app.
  12. Compare Firebase Authentication with a custom backend approach.

26. Interview Questions and Answers

Q1. What is email and password authentication?

Answer: It is an authentication method in which users register and sign in using an email address and a password.

Q2. What is the difference between authentication and authorization?

Answer: Authentication verifies a user's identity, while authorization determines which resources and operations that user can access.

Q3. What is Firebase Authentication?

Answer: Firebase Authentication is a managed service that provides APIs and infrastructure for user authentication, including email/password accounts and other sign-in methods.

Q4. Which Firebase method creates a user account?

Answer: createUserWithEmailAndPassword() creates an account using an email address and password.

Q5. Which method signs in an existing user?

Answer: signInWithEmailAndPassword() authenticates an existing account with an email address and password.

Q6. How can an application observe authentication state?

Answer: In the Firebase JavaScript SDK, onAuthStateChanged() notifies the application when the authentication state changes.

Q7. Why is authentication context useful?

Answer: It centralizes the current user and authentication initialization state, allowing screens and navigation to respond consistently to login and logout events.

Q8. How should passwords be stored?

Answer: Applications should not store plain-text passwords. A trusted authentication provider or backend should securely handle password verification and storage.

Q9. What is email verification?

Answer: Email verification helps confirm that a user can access the email address associated with the account.

Q10. How does password reset work?

Answer: The application requests a reset email from the authentication provider. The user follows the secure link to change the password.

Q11. Why is session persistence important?

Answer: It allows the application to restore the user's authenticated state across app restarts, according to the provider's persistence configuration.

Q12. What should happen after sign-out?

Answer: The authentication provider ends the session, the authentication state updates, and the application returns the user to the appropriate public screen.

Q13. Is client-side validation sufficient for security?

Answer: No. Client-side validation improves usability, but the authentication provider or backend must validate credentials and enforce security rules.

Q14. How can an application prevent access to protected data?

Answer: The application can use authentication state to control navigation, while the backend or database rules must independently enforce authentication and authorization.

Q15. What is the difference between Firebase JavaScript SDK and React Native Firebase?

Answer: The JavaScript SDK provides Firebase functionality through JavaScript APIs and requires appropriate React Native persistence configuration when needed. React Native Firebase integrates the native Firebase SDKs and requires compatible native configuration.

27. Quick Revision Checklist

  • Understand email/password authentication.
  • Know the difference between authentication and authorization.
  • Configure a suitable authentication provider.
  • Implement registration and login forms.
  • Validate email and password inputs.
  • Handle authentication loading and error states.
  • Observe authentication state centrally.
  • Configure session persistence appropriately.
  • Implement sign-out and protected screens.
  • Implement password recovery and email verification.
  • Never store plain-text passwords.
  • Enforce authorization on the backend or database.
  • Test offline, invalid-credential, and session-restoration scenarios.

28. Official Learning Resources

29. Conclusion

Email and password authentication is an essential feature for applications that provide personal accounts, protected screens, and user-specific information. React Native developers can implement this functionality using Firebase Authentication, React Native Firebase, or a secure custom backend.

A reliable implementation includes registration, login, validation, error handling, authentication-state management, session persistence, sign-out, password recovery, and email verification. Security also requires secure credential handling, appropriate session management, and backend authorization for protected resources.

By following these practices, developers can create a more secure and user-friendly authentication experience for Android and iOS applications.

whatsapp